

import CellBgGroup from "./cell_bg_group";
import CellGroup from "./cell_group";
import a_star from "./a_star";
import ParticleGroup from "./particle_group";
import util from "./util";
import TextTipGroup from "./text_tip_group";
import constants from "./constants";
import anim_util from "./anim_util";
import ScoreContainer from "./score_container";

// Learn TypeScript:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/typescript.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;

export enum GameState{
    Moving,
    Free,
    GameOver
}

@ccclass
export default class GameController extends cc.Component {

    private static _inst:GameController=null;

  

      @property({type:CellBgGroup})
     cellBgGroup:CellBgGroup=null;
 
     @property({type:CellGroup})
     cellGroup:CellGroup=null;

     @property({type:ParticleGroup})
     particleGroup:ParticleGroup=null;

     @property({type:TextTipGroup})
     textTipGroup:TextTipGroup=null;

     @property({type:ScoreContainer})
     scoreContainer:ScoreContainer=null;

     @property(cc.Node)
     gameOverTip:cc.Node=null;
 


     initCellCount=40;

     @property(cc.Node)
     hand:cc.Node=null;
    

     gameState:GameState=GameState.Moving;

     private _score=0;

     isNewGuy=true;

     tipAction=null;

     tipPoses=[];

     moveSteps=0;

    
    
 

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        GameController._inst=this;
      }

    start () {
        
    }

    
  

    static getInst(){
        return GameController._inst;
    }

    set score(value){
        this._score=value;
        if(this.scoreContainer!==null){
            this.scoreContainer.changeScore(value);
        }
    }

    get score(){
        return this._score;
    }



    async startGame(){
            this.cellBgGroup.node.getComponent(cc.Widget).updateAlignment();
            this.cellBgGroup.createCellBg();
            this.scoreContainer.init();
            this.score=0;
            this.moveSteps=0;
            await this.createRandomCells(this.initCellCount);
  
   
    }
    exitGame(){

    }

    

    async createRandomCells(count){
        let nodes= this.cellBgGroup.getRandomFreeCellBgs(count);
        if(nodes.length===0){
            return;
        }
        cc.director.emit(constants.GAME_EVENT.Merge);
        for(let i=0;i<nodes.length;i++){
         
            if(this.cellGroup.node.childrenCount>=this.cellBgGroup.cellBgRow*this.cellBgGroup.cellBgCol){
                break;
            }
            this.cellGroup.createCell(nodes[i],this.cellGroup.getRandomValue());
        }

        if(this.moveSteps===0){
            await util.sleep(3500);
        }
        else{
            await util.sleep(1500);
        }
 
           

        for(let col=0;col<this.cellBgGroup.cellBgs.length;col++){
            for(let row=0;row<this.cellBgGroup.cellBgs[col].length;row++){
                if(this.cellBgGroup.cellBgs[col][row].getComponent("cell_bg").cell!==null){
                    await this.checkIntergrate(this.cellBgGroup.cellBgs[col][row].getComponent("cell_bg").cell);
                }
            }
        }
        this.runTipTurtorial();
      

        this.gameState=GameState.Free;
    }

     async runTipTurtorial(){
         if(!this.isNewGuy||this.moveSteps>=1){
            return;
         }

        let tipCells:any= await this.getTipCells();

        cc.log(tipCells);
        
        this.tipPoses[0]=tipCells.from;
        this.tipPoses[1]=tipCells.to;

        this.hand.setPosition(this.tipPoses[0]);
        this.hand.active=true;
        this.hand.opacity=255;

        this.tipAction= this.hand.runAction(cc.repeatForever(cc.sequence(cc.scaleTo(0.5, 1.0, 1.0), cc.scaleTo(0.5, 0.7, 0.7),
        cc.scaleTo(0.5, 1.0, 1.0), cc.scaleTo(0.5, 0.7, 0.7),
        cc.moveTo(0.5,this.tipPoses[1]),cc.delayTime(0.5),
        cc.scaleTo(0.5, 1.0, 1.0), cc.scaleTo(0.5, 0.7, .7),
        cc.scaleTo(0.5, 1.0, 1.0), cc.scaleTo(0.5,.7, .7),cc.fadeOut(0.5),cc.callFunc(()=>{
            this.hand.setPosition(this.tipPoses[0]);
            this.hand.opacity=255;
        }))));
        
    }

    getTipCells(){
        return new Promise((res)=>{
            let freeCellBg=[];
            for(let mi=0;mi<this.cellBgGroup.cellMap.length;mi++){
                for(let mj=0;mj<this.cellBgGroup.cellMap[0].length;mj++){
                    // if(this.cellBgGroup.cellMap[mi][mj]===0&&a_star.countAroundPointBusy(this.cellBgGroup.cellBgs[mi][mj].getComponent("cell_bg").colRowPos,this.cellBgGroup.cellMap).length>=1){
                    //     freeCell.push(cc.v2(mi,mj));
                    // }
                    if(this.cellBgGroup.cellMap[mi][mj]===0){
                        freeCellBg.push(cc.v2(mi,mj));
                    }
                }
            }

            // cc.log(freeCell);
            for(let i=0;i<this.cellGroup.node.childrenCount;i++){
                for (const cellBg of freeCellBg) {
                    let curCell=this.cellGroup.node.children[i].getComponent("cell");
                    let roads=a_star.searchRoad(this.cellBgGroup.cellMap,curCell.colRowPos.x,
                        curCell.colRowPos.y,cellBg.x,cellBg.y);

                    if(roads.length>0){
                        for (const c of a_star.countAroundPointBusy(roads[roads.length-1],this.cellBgGroup.cellMap)) {
                            if((c.x!==curCell.colRowPos.x&&c.y!==curCell.colRowPos.y)&&this.cellBgGroup.cellBgs[c.x][c.y].getComponent("cell_bg").cell.getComponent("cell").value===
                             curCell.value){
                                cc.log(curCell.colRowPos,cellBg,c);
                                res({from:curCell.node.getPosition(),to:this.cellBgGroup.cellBgs[cellBg.x][cellBg.y].getPosition()});
                                return;
                            }
                        }
                    }
                }
            }
        });
    }


   


    moveSelectCell(cellBgNode){
        if(this.gameState===GameState.Moving){
            return;
        }
        this.gameState=GameState.Moving;
        if(this.tipAction!==null){
            this.hand.stopAction(this.tipAction);
            this.tipAction=null;
            this.hand.active=false;
        }

        this.cellGroup.unschedule(this.cellGroup.runSelectAnim);
        this.cellGroup.selectCell.stopAction(this.cellGroup.selectAction);

        let roads=a_star.searchRoad(this.cellBgGroup.cellMap,GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.x,
        GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.y,cellBgNode.getComponent("cell_bg").colRowPos.x,cellBgNode.getComponent("cell_bg").colRowPos.y);
        if(roads.length===0){
            cc.log("不能移动到这",this.cellBgGroup.cellMap);
            this.gameState=GameState.Free;
            return;
        }

        let moves:any=[];
     
        roads.map((road)=>{
            moves.push(cc.moveTo(0.3,this.cellBgGroup.cellBgs[road.x][road.y].getPosition()));
        });
        moves.push(cc.spawn(cc.scaleTo(0.05,1,1),cc.fadeTo(0.05,255)));
        moves.push(cc.delayTime(0.05));
        moves.push(cc.callFunc(async()=>{
        this.cellBgGroup.cellBgs[GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.x][GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.y]
        .getComponent("cell_bg").cell=null;

        this.cellBgGroup.cellMap[GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.x][GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.y]=0;
        this.cellBgGroup.cellMap[cellBgNode.getComponent("cell_bg").colRowPos.x][cellBgNode.getComponent("cell_bg").colRowPos.y]=1;
        GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos=cellBgNode.getComponent("cell_bg").colRowPos;
        this.cellBgGroup.cellBgs[GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.x][GameController.getInst().cellGroup.selectCell.getComponent("cell").colRowPos.y]
        .getComponent("cell_bg").cell=GameController.getInst().cellGroup.selectCell;

        await this.checkIntergrate(GameController.getInst().cellGroup.selectCell);
       
        GameController.getInst().cellGroup.getComponent("cell_group").cancelSelect();
        await this.createRandomCells(40);
        if(this.cellGroup.node.childrenCount===this.cellBgGroup.cellBgRow*this.cellBgGroup.cellBgCol){
            this.gameState=GameState.GameOver;
            this.gameOver();
        }
        else{
            this.cellGroup.selectCell=null;
            this.gameState=GameState.Free;
        }

        this.moveSteps++;

        },this));
        GameController.getInst().cellGroup.selectCell.runAction(cc.sequence(moves));
    }
 
 
    async checkIntergrate(checkCell){
        
        return new Promise(async(res)=>{
            let v:any=true;
            while(v===true){
            v=false;
            let cells=[];
            a_star.countAroundPoint(checkCell.getComponent("cell").colRowPos).map((pos)=>{
                if(pos.x<this.cellBgGroup.cellMap.length&&pos.x>=0&&pos.y<this.cellBgGroup.cellMap[0].length&&pos.y>=0&&this.cellBgGroup.cellMap[pos.x][pos.y]===1){
                     cells.push(this.cellBgGroup.cellBgs[pos.x][pos.y].getComponent("cell_bg").cell);
                }
            });
            for (let cell of cells) {
                if(cell.getComponent("cell").value===checkCell.getComponent("cell").value){
                    await this.intergrate(checkCell,cell);
                    checkCell=cell;
                    v=true;
                    break;
               }
            }
           }
        res();
        });
      
    }

    async intergrate(from,to){
        return new Promise((res)=>{
            from.runAction(cc.sequence(cc.moveTo(0.5,to.getPosition()),cc.callFunc(()=>{
                let addScore=to.getComponent("cell").value;
                this.score+=addScore;
                cc.log(this.score);

                this.cellBgGroup.cellMap[from.getComponent("cell").colRowPos.x][from.getComponent("cell").colRowPos.y]=0;
                this.cellBgGroup.cellMap[to.getComponent("cell").colRowPos.x][to.getComponent("cell").colRowPos.y]=1;
                to.getComponent("cell").value=to.getComponent("cell").value*2;
                this.cellBgGroup.cellBgs[from.getComponent("cell").colRowPos.x][from.getComponent("cell").colRowPos.y].getComponent("cell_bg").cell=null;
                this.cellBgGroup.cellBgs[to.getComponent("cell").colRowPos.x][to.getComponent("cell").colRowPos.y].getComponent("cell_bg").cell=to;
                GameController.getInst().cellGroup.selectCell=to;

                let textTipNode= this.textTipGroup.getNewNode();
                let textTipLabel=textTipNode.getComponent(cc.Label);
                textTipNode.setPosition(to.getPosition());
                textTipLabel.string="+"+addScore;

                
                GameController.getInst().cellGroup.died(from);
                this.cellGroup.setParticleNode(to.getPosition(),to.getComponent("cell").value);
                cc.director.emit(constants.GAME_EVENT.Merge);
                textTipNode.runAction(cc.spawn(cc.moveBy(1,0,100),cc.fadeOut(1)));
                res();
                
              
            },this)));
        });
    }

    
    gameOver(){
        cc.log("gameover..!");
        anim_util.runAnimBottomToMid(this.gameOverTip,()=>{
            cc.director.loadScene("gameover");
        });
    }


    // setEventControl(){
    //     this.node.on(cc.Node.EventType.TOUCH_START,(t)=>{
    //         this.cellBgGroup.select();
    //     },this);
    //     // this.node.on(cc.Node.EventType.TOUCH_MOVE,
    //     //     function(t){cc.log("cc.Node.EventType.TOUCH_MOVE ")},this)
             
    //     this.node.on(cc.Node.EventType.TOUCH_CANCEL,(t)=>{
    //         this.cellBgGroup.cancelSelect();
    //     },this);
             
        
    // }



    // update (dt) {}
}
